/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package pr1.gui;

import java.awt.Color;
import java.util.Collection;
import org.math.plot.Plot2DPanel;
import pr1.AlgoritmoGenetico;
import pr1.cromosoma.Cromosoma;
import pr1.cromosoma.CromosomaFactory;
import pr1.cruce.EstrategiaCruce;
import pr1.seleccion.EstrategiaSeleccion;

/**
 *
 * @author Gonzalo Ortiz Jaureguizar (gortiz at software.imdea.org)
 */
public class AGRunner {
    int generaciones;
    int tamPoblacion;
    double probCruce;
    double probMutacion;
    double precision;
    CromosomaFactory factory;
    EstrategiaSeleccion seleccion;
    EstrategiaCruce cruce;
    AlgoritmoGenetico ag;
    int elitismo;

    public void plot(Plot2DPanel plot, boolean maximizar) {
        factory.setPrecision(precision);
        int guardados = elitismo * tamPoblacion / 100;
        ag = new AlgoritmoGenetico(tamPoblacion, guardados, maximizar, factory);

        ag.setCruce(cruce);
        ag.setProbCruce(probCruce/100);
        ag.setProbMutacion(probMutacion/100);
        ag.setSeleccion(seleccion);

        double [] mejorHistorico = new double[generaciones+1];
        double [] mejorActual = new double[generaciones+1];
        double [] media = new double[generaciones+1];

        plot.removeAllPlots();

        mejorHistorico[0] = ag.getMejor().getAptitud();
        mejorActual[0] = ag.getMejorActual().getAptitud();
        media[0] = calcularMedia(ag.getPoblacion());

        for(int i = 1; i <= generaciones; i++) {
            ag.nuevaIteracion();
            mejorHistorico[i] = ag.getMejor().getAptitud();
            mejorActual[i] = ag.getMejorActual().getAptitud();
            media[i] = calcularMedia(ag.getPoblacion());
        }

        plot.addLinePlot("Maximo historico", Color.BLUE, mejorHistorico);
        plot.addLinePlot("Maximo actual", Color.RED, mejorActual);
        plot.addLinePlot("Media", Color.GREEN, media);
    }

    private double calcularMedia(Collection<Cromosoma> cromosomas) {
        double media = 0;
        for(Cromosoma c : cromosomas) {
            media += c.getAptitud();
        }
        return media / cromosomas.size();
    }

    public boolean chequearCondicionesIniciales() {
        if(generaciones <= 0) {
            throw new IllegalStateException("El número de generaciones no es positivo");
        }
        if(tamPoblacion <= 0) {
            throw new IllegalStateException("El tamaño de la población no es positivo");
        }
        if(probCruce < 0) {
            throw new IllegalStateException("La probabilidad de cruce no puede ser negativa");
        }
        if(probMutacion < 0) {
            throw new IllegalStateException("La probabilidad de mutación no puede ser negativa");
        }
        if(precision <= 0) {
            throw new IllegalStateException("La precisión debe positiva");
        }
        if(factory == null) {
            throw new IllegalStateException("Se debe iniciar la factoría");
        }
        if(cruce == null) {
            throw new IllegalStateException("Se debe iniciar la estrategia de cruce");
        }
        if(seleccion == null) {
            throw new IllegalStateException("Se debe iniciar la estrategia de selección");
        }
        return true;
    }

    public CromosomaFactory getFactory() {
        return factory;
    }

    public void setFactory(CromosomaFactory factory) {
        this.factory = factory;
    }

    public int getTamPoblacion() {
        return tamPoblacion;
    }

    public void setTamPoblacion(int tamPoblacion) {
        this.tamPoblacion = tamPoblacion;
    }

    public EstrategiaCruce getCruce() {
        return cruce;
    }

    public void setCruce(EstrategiaCruce cruce) {
        this.cruce = cruce;
    }

    public int getGeneraciones() {
        return generaciones;
    }

    public void setGeneraciones(int generaciones) {
        this.generaciones = generaciones;
    }

    public double getPrecision() {
        return precision;
    }

    public void setPrecision(double precision) {
        this.precision = precision;
    }

    public double getProbCruce() {
        return probCruce;
    }

    public void setProbCruce(int probCruce) {
        this.probCruce = probCruce;
    }

    public double getProbMutacion() {
        return probMutacion;
    }

    public void setProbMutacion(int probMutacion) {
        this.probMutacion = probMutacion;
    }

    public EstrategiaSeleccion getSeleccion() {
        return seleccion;
    }

    public void setSeleccion(EstrategiaSeleccion seleccion) {
        this.seleccion = seleccion;
    }

    public int getElitismo() {
        return elitismo;
    }

    public void setElitismo(int elitismo) {
        this.elitismo = elitismo;
    }
}
